package main

import "fmt"

/*
	• 无需声明原型。
    • 支持不定 变参。
    • 支持多返回值。
    • 支持命名返回参数。
    • 支持匿名函数和闭包。
    • 函数也是一种类型，一个函数可以赋值给变量。
    • 不支持 嵌套 (nested) 一个包不能有两个名字一样的函数。
    • 不支持 重载 (overload)
    • 不支持 默认参数 (default parameter)。
*/

/*
// 参数可有可无，多有多个不同||相同数据类型的参数，返回值可有可无
func 函数名(参数1 数据类型,...) 返回值{}
*/
// 无参无返回值函数
func noParametersNoReturnValueFunction() {
	fmt.Println("我是无参无")
}

// 有参无返回值函数
func thereAreArgumentsButNoReturnValueFunctions(my string) {
	fmt.Println(my + "有参无返回值函数")
}

// 无参有返回值函数
func noParametersReturnValueFunction() (int, string) {
	return 24, "man"
}

// 有参有返回值函数 -- 函数作为参数
func thereAreArParametersReturnValueFunction(fn func(string), s1 string) func() {
	// 返回一个闭包，捕获外部参数s1
	return func() {
		fn(s1) // 调用原始函数并传入s1
	}
}

// 无固定值参数
func thereIsNoFixedValueParameter(args ...int) {
	count := 0
	for i := range args {
		count += args[i]
		fmt.Println(args[i])
	}
	fmt.Println("count=", count)
}

// 参数传递
// 值传递：指在调用函数时将实际参数复制一份传递到函数中，这样在函数中如果对参数进行修改，将不会影响到实际参数。
// 引用传递：是指在调用函数时将实际参数的地址传递到函数中，那么在函数中对参数所进行的修改，将影响到实际参数。
// 注意：map,slice,chan,指针,interface默认以引用模式传递
func main() {
	noParametersNoReturnValueFunction()
	thereAreArgumentsButNoReturnValueFunctions("我是")
	number, str := noParametersReturnValueFunction()
	fmt.Println(number, str)

	// 定义一个需要字符串参数的函数
	printMessage := func(msg string) {
		println("Message:", msg)
	}
	// 创建一个封装了printMessage的新函数
	newFunc := thereAreArParametersReturnValueFunction(printMessage, "Hello World")
	// 调用新函数，无需参数
	newFunc() // 输出: Message: Hello World

	thereIsNoFixedValueParameter(9, 7, 4, 6)
}
